<?php

declare(strict_types=1);


namespace App\CustHub\Mapper;

use App\CustHub\Model\ChSubUser;
use App\CustHub\Model\ChUser;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\Config\Annotation\Value;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractMapper;
use Mine\Annotation\Transaction;
use Mine\MineModel;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class ChSubUserMapper extends AbstractMapper
{

    #[Inject]
    protected ChUserMapper $userMapper;

    public function assignModel()
    {
        $this->model = ChSubUser::class;
    }

    #[Value('cache.default.prefix')]
    protected string $prefix;


    public function getPageList(?array $params, bool $isScope = true, string $pageName = 'page'): array
    {
        $query = $this->model::query()
            ->with(['roles' => function ($query) {
                $query->select(['id','name']);
            },'ext' => function ($query) {
                $query->with(['group'=>function ($query) {
                    $query->select(['id','name']);
                }]);
            }]);

        $paginate = $this->handleSearch($query,$params)
            ->orderBy('created_at','desc')
            ->paginate((int)($params['page_size'] ?? MineModel::PAGE_SIZE));

        return $this->setPaginate($paginate, $params);
    }


    public function handlePageItems(array $items,array $params)
    {
        $permissionMap = ['仅自己','全部子账号','自定义范围'];
        $items = array_map(function ($item) use ($params,$permissionMap) {
            return [
                'id' => $item['id'],
                'username' => $item['username'],
                'account' => $item['account'],
                'seat_quota' => $item['ext']['seat_quota'],
                'use_num' => 0,
                'group_id' => $item['ext']['group_id'],
                'data_scope' => $item['ext']['data_scope'],
                'data_scope_extra' => $item['ext']['data_scope_extra'],
                'data_scope_allow' => $item['ext']['data_scope_allow'],
                'group_name' => $item['ext']['group']['name'] ?? '未分组',
                'permission' => $permissionMap[$item['ext']['data_scope']],
                'role_id' => $item['roles'][0]['id'] ?? '',
                'role_name' => $item['roles'][0]['name'] ?? '',
            ];
        }, $items);

        return $items;
    }


    /**
     * 根据ID获取用户信息
     * @param mixed $id
     * @return ChUser|Builder|null
     */
    #[Cacheable(prefix: 'ch_sub_user_info',value: 'id_#{id}')]
    public function findById(mixed $id): ChUser|Builder|null
    {
        return $this->model::with(['ext'])->where('id',$id)->first();
    }

    /**
     * 删除用户缓存
     * @param mixed $id
     * @return void
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws \RedisException
     */
    public function clearCache(mixed $id): void
    {
        $redis = redis();
        $keyOne = $this->prefix . 'ch_sub_user_info:id_'.$id;
        $redis->del([$keyOne]);
    }

    /**
     * 检查用户密码
     */
    public function checkPass(string $password, string $hash): bool
    {
        return $this->model::passwordVerify($password, $hash);
    }

    /**
     * 通过账号检查是否存在.
     */
    public function existsByAccount(string $account,mixed $id = ''): bool
    {
        return $this->model::query()
            ->when(!empty($id),function ($query) use ($id){
                $query->where('id','<>',$id);
            })
            ->where('account', $account)
            ->exists();
    }

    #[Transaction]
    public function save(array $data): mixed
    {
        $role_ids = $data['role_ids'] ?? [];
        $extData = [
            'expire_time' => strtotime($data['expire_time']),
            'data_scope' => $data['data_scope'] ?? 0,
            'data_scope_extra' => $data['data_scope_extra'] ?? '',
            'data_scope_allow' => $data['data_scope_allow'] ?? 0,
            'seat_quota' => $data['seat_quota'] ?? -1,
        ];

        $data['parent_id'] = $data['main_uid'];
        $data['joinip'] = get_client_ip();
        $data['invite_code'] = make_coupon_card();

        $this->filterExecuteAttributes($data, true);

        $user = $this->model::create($data);

        $extData['uid'] = $user->id;
        $user->ext()->create($extData);
        $user->roles()->sync($role_ids, false);
        return $user->id;
    }

    #[Transaction]
    public function update(mixed $id, array $data): bool
    {
        $role_ids = $data['role_ids'] ?? [];

        $extData = [
            'expire_time' => strtotime($data['expire_time']),
            'data_scope' => $data['data_scope'] ?? 0,
            'data_scope_extra' => $data['data_scope_extra'] ?? '',
            'data_scope_allow' => $data['data_scope_allow'] ?? 0,
            'seat_quota' => $data['seat_quota'] ?? -1,
        ];

        $this->filterExecuteAttributes($data, true);

        $result = parent::update($id, $data);
        $this->clearCache($id);
        $this->userMapper->clearCache($id);
        $user = $this->model::find($id);
        if ($user && $result) {
            ! empty($role_ids) && $user->roles()->sync($role_ids);
            $user->ext()->update($extData);
            return true;
        }
        return false;
    }

    /**
     * 真实批量删除用户.
     */
    #[Transaction]
    public function realDelete(array $ids): bool
    {
        foreach ($ids as $id) {
            $user = $this->model::withTrashed()->find($id);
            if ($user) {
                $user->roles()->detach();
                if($user->ext->group_id != 0){
                    $user->ext->group->decrement('account_num');
                }
                $user->ext()->delete();
                $user->forceDelete();
            }
        }
        return true;
    }

    public function handleSearch(Builder $query, array $params): Builder
    {

        $query->where('parent_id',$params['main_uid']);

        if(isset($params['username'])){
            $query->where('username','like','%'.$params['username'].'%');
        }

        if(isset($params['group_id']) && filled($params['group_id']) && $params['group_id'] != -1){
            $groupId = $params['group_id'];
            $query->whereHas('ext',function ($query) use ($groupId){
                $query->where('group_id',$groupId);
            });
        }

        return $query;
    }


    /**
     * 初始化用户密码
     */
    public function initUserPassword(int $id, string $password): bool
    {
        $model = $this->model::find($id);
        if ($model) {
            $model->password = $password;
            return $model->save();
        }
        return false;
    }
}